package cn.zero.wechat.util;


import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.ClientProtocolException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;

import cn.zero.service.WechatService;
import cn.zero.util.AppStringUtils;
import cn.zero.util.UtilContext;
import cn.zero.util.WebUtil;
import cn.zero.wechat.AccessTokenModel;
import cn.zero.wechat.config.WechatCommonConfig;
import cn.zero.wechat.req.WechatJSTicket;
import cn.zero.wechat.resp.WechatError;

public class WechatUtil2 {
	
	private static Logger logger = LoggerFactory.getLogger(WechatUtil2.class);

	final static String TEMPLATE_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s";
	
	final static String CUSTOMER_MSG_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=%s";
	
	public static String WECHAT_TOKEN_SERVER_URL;
	
	/**
	 * 向access_token服务器注册appId，appSecrect，以便调用缓存access_token
	 */
	public static void initWechatServerConfig() {
		try {
			WebUtil.getUrlData(WECHAT_TOKEN_SERVER_URL + String.format("/api/wechat/inittoken?appId=%s&appSecret=%s", WechatCommonConfig.wechatConfig().getWeixin().getAppId(), WechatCommonConfig.wechatConfig().getWeixin().getSecret()));
		} catch (Exception e) {
			
		}
	}
	
	public static AccessTokenModel getAuthorizeAccessToken(String code) {
		String retData = null; 
		try {
			retData = WebUtil.getUrlData(WECHAT_TOKEN_SERVER_URL + String.format("/api/wechat/getauthtoken?appId=%s&code=%s", WechatCommonConfig.wechatConfig().getWeixin().getAppId(), code));
		} catch (Exception e) {
			return null;
		}
		return JSONObject.parseObject(retData, AccessTokenModel.class);
	}

	public static void initAccessToken() {
		try {
			String url = WECHAT_TOKEN_SERVER_URL + "/api/wechat/init";
			WebUtil.getUrlData(url);
		} catch (Exception e){
			
		}
	}
	
	public static String getAccessToken() {
		String tokenUrl = WECHAT_TOKEN_SERVER_URL +"/api/wechat/getaccesstoken?appId=" + WechatCommonConfig.wechatConfig().getWeixin().getAppId();
		try {
			return WebUtil.getUrlData(tokenUrl);
		} catch (Exception e) {
			return null;
		}
	}
	
	//TODO 这里需要有个重新获取值的机制
	public static String getAccessTokenLocal() {
		if (WechatCommonConfig.getAccessTokenModel() == null || WechatCommonConfig.getAccessTokenModel().isAccessTokenExpired()) {
			try {
				String access_token_url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
						WechatCommonConfig.wechatConfig().getWeixin().getAppId(), WechatCommonConfig.wechatConfig().getWeixin().getSecret());
				String retData = WebUtil.getUrlData(access_token_url);
				WechatCommonConfig.updateAccessTokenModel(JSONObject.parseObject(retData, AccessTokenModel.class));
			} catch (Exception e) {
				e.printStackTrace();
			}
			 
		}
		return WechatCommonConfig.getAccessTokenModel().getAccess_token();
	}
	
	public static String getJSTicket() {
		if (WechatCommonConfig.getWechatJSTicket() == null || WechatCommonConfig.getWechatJSTicket().isExpired()) {
			try {
				String ticket_url = String.format("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi",
						WechatUtil2.getAccessToken());
				String retData = WebUtil.getUrlData(ticket_url);
				WechatCommonConfig.updateWechatJSTicket(JSONObject.parseObject(retData, WechatJSTicket.class));
			} catch (Exception e) {
				e.printStackTrace();
			}
			 
		}
		return WechatCommonConfig.getWechatJSTicket().getTicket();
	}
	
	public static String getWechatInfo(String openid) {
		try {
			String url = String.format("https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN",
				getAccessToken(), openid);
			return WebUtil.getUrlData(url);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	public static String getWechatAuthorizeInfo(String accessToken, String openid) {
		String url = String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN",
				accessToken, openid);
		try {
			return WebUtil.getUrlData(url);
		} catch (Exception e) {
			return null;
		}
	}
	
	public static String getTemplateMsgSendUrl() {
		return String.format(TEMPLATE_SEND_URL, getAccessToken());
	}
	
	/**
	 * 发送客服文字消息
	 * @param openid
	 * @param msg
	 */
	public static boolean sendCustomerTextMsg(String openid, String msg) {
		String reqStr = String.format("{\"touser\":\"%s\",\"msgtype\":\"text\",\"text\":{\"content\":\"%s\"}}", openid, msg);
		try {
			WechatError wechatError =  WechatError.fromJson(WebUtil.getPostUrlData(String.format(CUSTOMER_MSG_SEND_URL, getAccessToken()), reqStr));
			return wechatError.getErrorCode() == 0 && "ok".equals(wechatError.getErrorMsg());
		}catch (Exception e) {
			logger.error(e.getMessage());
		}
		return false;
	}
	
	public static String getExpireQrcode(String sceneStr, long seconds) {
		try {
			JSONObject json = new JSONObject();
			json.put("expire_seconds", seconds);
			json.put("action_name", "QR_STR_SCENE");
			
			JSONObject jsonInfo = new JSONObject();
			JSONObject jsonScene = new JSONObject();
			
			jsonScene.put("scene_str",  sceneStr);
			jsonInfo.put("scene", jsonScene);
			json.put("action_info", jsonInfo);
			
			String url = String.format("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s",
					getAccessToken());
			
			String respData = WebUtil.getPostUrlData(url, json.toJSONString());
			
			JSONObject respJson = JSONObject.parseObject(respData);
			
			return String.format("https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s",
					respJson.get("ticket"));
			
		} catch (Exception e) {
			
		}
		return StringUtils.EMPTY;
	}

	/**
	 *
	 * @param type
	 *            媒体文件类型，分别有图片（image）、语音（voice）、视频（video）和缩略图（thumb）
	 * @param file
	 *            需要上传的文件
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws KeyManagementException
	 * @throws NoSuchProviderException
	 * @throws NoSuchAlgorithmException
	 */
	public static String uploadMedia(String type, File file) throws ClientProtocolException, IOException,
			KeyManagementException, NoSuchAlgorithmException, NoSuchProviderException {
		String reqUrl = String.format("https://api.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=%s",
				UtilContext.getBean(WechatService.class).getAccessToken(null), type);
		TrustManager[] tm = { new JEEWechatX509TrustManager() };
		SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
		sslContext.init(null, tm, new SecureRandom());
		SSLSocketFactory ssf = sslContext.getSocketFactory();
		URL url = new URL(reqUrl);
		HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
		conn.setSSLSocketFactory(ssf);
		conn.setRequestMethod("POST");
		conn.setDoInput(true);
		conn.setDoOutput(true);
		conn.setUseCaches(false);

		conn.setRequestProperty("Connection", "Keep-Alive");
		conn.setRequestProperty("Charset", "UTF-8");
		String boundary = "----------" + System.currentTimeMillis();// 设置边界
		conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);

		StringBuilder headBuff = new StringBuilder();
		headBuff.append("--" + boundary + "\r\n");// 必须多两道线
		headBuff.append("Content-Disposition: form-data;name=\"file\";filename=\"" + file.getName() + "\"\r\n");
		headBuff.append("Content-Type:application/octet-stream\r\n\r\n");
		byte[] head = headBuff.toString().getBytes("utf-8");

		// 获得输出流
		OutputStream out = new DataOutputStream(conn.getOutputStream());
		// 输出表头
		out.write(head);

		DataInputStream in = new DataInputStream(new FileInputStream(file));
		int bytes = 0;
		byte[] bufferOut = new byte[1024];
		while ((bytes = in.read(bufferOut)) != -1) {
			out.write(bufferOut, 0, bytes);
		}
		in.close();

		byte[] foot = ("\r\n--" + boundary + "--\r\n").getBytes("utf-8");// 定义数据分隔线
		out.write(foot);
		out.flush();
		out.close();
		return AppStringUtils.convertStreamToString(conn.getInputStream());
	}

	

	public static String sendImageMessage(String openid, String mediaId) throws ClientProtocolException, IOException {
		JSONObject jsonObj = new JSONObject();
		jsonObj.put("touser", openid);
		jsonObj.put("msgtype", "image");
		JSONObject jsonContent = new JSONObject();
		jsonContent.put("media_id", mediaId);
		jsonObj.put("image", jsonContent);
		String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token="
				+ UtilContext.getBean(WechatService.class).getAccessToken(null);
		return WebUtil.getUrlData(url, jsonObj.toJSONString());
	}

	/**
	 * 获取更新普通微信菜单带token链接
	 *
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	private static String getWechatMenuUrl() throws ClientProtocolException, IOException {
		return String.format("https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%s", getAccessToken());
	}

	/**
	 * 获取新标组带token链接
	 *
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	private static String getTagsQueryUrl() throws ClientProtocolException, IOException {
		return String.format("https://api.weixin.qq.com/cgi-bin/tags/get?access_token=%s", getAccessToken());
	}

	/**
	 * 获取更新个性化微信菜单带token链接
	 *
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	private static String getWechatMenuConditionalMenuUrl() throws ClientProtocolException, IOException {
		return String.format("https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token=%s", getAccessToken());
	}

	

}
